import json

from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.mixins import LoginRequiredMixin
from django_redis import get_redis_connection

from apps.carts.utils import merge_cart_cookie_to_redis
from apps.goods.models import SKU
from apps.users.models import User, Address
from django.shortcuts import render, redirect
from django.urls import reverse

from django.views import View
from django import http
import re

from apps.oauth.views import logger
from apps.users.utils import check_verify_token
from utils.response_code import RETCODE


class RegisterView(View):
    """用户注册"""

    def get(self, request):
        """
        提供注册界面
        :param request: 请求对象
        :return: 注册界面
        """
        return render(request, 'register.html')

    def post(self, request):
        """
        实现用户注册
        :param request: 请求对象
        :return: 注册结果
        """
        username = request.POST.get('username')
        password = request.POST.get('password')
        password2 = request.POST.get('password2')
        mobile = request.POST.get('mobile')
        allow = request.POST.get('allow')

        # 判断参数是否齐全
        # if not all([username, password, password2, mobile, allow]):
        if not all([username, password, password2, mobile]):
            return http.HttpResponseBadRequest('缺少必传参数')
        # 判断用户名是否是5-20个字符
        if not re.match(r'^[a-zA-Z0-9_]{5,20}$', username):
            return http.HttpResponseBadRequest('请输入5-20个字符的用户名')
        # 判断密码是否是8-20个数字
        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return http.HttpResponseBadRequest('请输入8-20位的密码')
        # 判断两次密码是否一致
        if password != password2:
            return http.HttpResponseBadRequest('两次输入的密码不一致')
        # 判断手机号是否合法
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseBadRequest('请输入正确的手机号码')
        # 判断是否勾选用户协议
        # if allow != 'on':
        #     return http.HttpResponseBadRequest('请勾选用户协议')

        user = User.objects.create_user(username=username,
                                        password=password,
                                        mobile=mobile)

        from django.contrib.auth import login, authenticate
        login(request, user)

        # 4.返回相应, 想跳转到首页去
        # reverse 是通过 name 来获取 视图的路由
        # path = reverse('namespace:name')
        path = reverse('contents:index')
        # path /
        response = redirect(path)
        return response
        return HttpResponse('注册成功')

        # from django.db import DatabaseError
        #
        # # 保存注册数据
        # try:
        #     User.objects.create_user(username=username, password=password, mobile=mobile)
        # except DatabaseError:
        #     return render(request, 'register.html', {'register_errmsg': '注册失败'})
        #
        # # 响应注册结果
        # return http.HttpResponse('注册成功，重定向到首页')


class UsernameCountView(View):
    def get(self, request, username):
        # 1.获取用户名
        # 2.我们根据查询的用户名的数量来判断是否重复 0表示不重复 1表示重复
        count = User.objects.filter(username=username).count()
        # 3.返回相应(返回JSON数据)
        return http.JsonResponse({'count': count})


class MobileCountView(View):
    """判断手机号是否重复注册"""

    def get(self, request, mobile):
        count = User.objects.filter(mobile=mobile).count()
        return http.JsonResponse({'count': count})


class LoginView(View):
    def get(self, request):
        return render(request, 'login.html')

    def post(self, request):
        # 接受数据
        username = request.POST.get('username')
        password = request.POST.get('pwd')
        remembered = request.POST.get('remembered')
        next = request.POST.get('next')
        # 校验数据
        # 2.1验证参数是齐全
        # 2.2 判断用户名是否符合正则
        # 2.3 判断密码是否符合正则
        if not all([username, password]):
            return http.HttpResponseBadRequest('缺少参数')
        if not re.match(r'^[a-zA-Z0-9_]{5,20}$', username):
            return http.HttpResponseBadRequest('请输入正确的用户名或者手机号')
        if not re.match(r'^[a-zA-Z0-9]{8,20}$', password):
            return http.HttpResponseBadRequest('密码最少5位,最多20位')

        # 3.登陆(验证用户名和密码是否正确)
        user = authenticate(username=username, password=password)
        if user is None:
            return http.HttpResponseBadRequest('账号或者密码错误')

        # 4.设置登陆状态(session)
        login(request, user)
        if remembered != 'on':
            request.session.set_expiry(None)
        else:
            request.session.set_expiry(0)

            # 5.返回相应
        if next:
            response = redirect(next)
        else:
            response = redirect(reverse('contents:index'))

        # response.set_cookie('username', user.username, max_age=15 * 24 * 60 * 60)
        response.set_cookie('username', user.username)
        # merge_cart_cookie_to_redis(request,user,response)
        return response


class LogoutView(View):
    def get(self, request):
        logout(request)
        response = redirect(reverse('contents:index'))
        response.delete_cookie('username')
        return response


class UserInfoView(LoginRequiredMixin, View):
    LOGIN_URL = '/login/'

    def get(self, request):
        context = {
            'username': request.user.username,
            'mobile': request.user.mobile,
            'email': request.user.email,
            'email_active': request.user.email_active
        }
        return render(request, 'user_center_info.html', context=context)


class EmailView(View):
    def put(self, request):
        # 接收
        user = request.user
        body = request.body
        body_str = body.decode()
        data = json.loads(body_str)
        email = data.get('email')
        # 检验
        if not email:
            return http.HttpResponseBadRequest('缺少email')
        if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
            return http.HttpResponseBadRequest('请输入合法的邮箱')
        # 赋值
        try:
            user.email = email
            user.save()
        except Exception as e:
            logger.error(e)
            return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '添加邮箱失败'})

        from celery_tasks.email.tasks import send_active_email
        send_active_email.delay(email, request.user.id)

        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '添加邮箱成功'})


class EmailActiveView(View):
    def get(self, request):
        # 接收
        token = request.GET.get('token')
        # 检验
        if not token:
            return http.HttpResponseBadRequest('缺少token')
        user_id = check_verify_token(token)
        if not user_id:
            return http.HttpResponseBadRequest('无效的token')
        try:
            user = User.objects.get(id=user_id)
        except User.DoesNotExist:
            return http.HttpResponseBadRequest('没有此用户')
        try:
            user.email_active = True
            user.save()
        except Exception as e:
            logger.error(e)
            return http.HttpResponseBadRequest('激活失败')

        return redirect(reverse('users:center'))


# 展示地址
class AddressView(LoginRequiredMixin, View):
    def get(self, request):
        # 根据条件查询
        addresses = Address.objects.filter(user=request.user, is_deleted=False)
        address_list = []
        for address in addresses:
            address_list.append({
                "id": address.id,
                "title": address.title,
                "receiver": address.receiver,
                "province": address.province.name,
                "province_id": address.province_id,
                "city": address.city.name,
                "city_id": address.city_id,
                "district": address.district.name,
                "district_id": address.district_id,
                "place": address.place,
                "mobile": address.mobile,
                "tel": address.tel,
                "email": address.email
            })
        context = {
            'default_address_id': request.user.default_address_id,
            'addresses': address_list,
        }

        return render(request, 'user_center_site.html', context=context)


# 新增地址
class CreateAddressView(View):
    def post(self, request):
        # count = request.user.addresses.count()
        # if count >= constants.USER_ADDRESS_COUNTS_LIMIT:
        #     return http.HttpResponseBadRequest('超过地址数量上限')

        # 接受数据
        json_dict = json.loads(request.body.decode())
        receiver = json_dict.get('receiver')
        province_id = json_dict.get('province_id')
        city_id = json_dict.get('city_id')
        district_id = json_dict.get('district_id')
        place = json_dict.get('place')
        mobile = json_dict.get('mobile')
        tel = json_dict.get('tel')
        email = json_dict.get('email')
        # 校验数据
        if not all([receiver, province_id, city_id, district_id, place, mobile]):
            return http.HttpResponseBadRequest('缺少必传参数')
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseBadRequest('参数mobile有误')
        if tel:
            if not re.match(r'^(0[0-9]{2,3}-)?([2-9][0-9]{6,7})+(-[0-9]{1,4})?$', tel):
                return http.HttpResponseBadRequest('参数tel有误')
        if email:
            if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
                return http.HttpResponseBadRequest('参数email有误')
        # 保存地址信息
        try:
            address = Address.objects.create(
                user=request.user,
                title=receiver,
                receiver=receiver,
                province_id=province_id,
                city_id=city_id,
                district_id=district_id,
                place=place,
                mobile=mobile,
                tel=tel,
                email=email
            )
        except Exception as e:
            logger.error(e)
            return http.JsonResponse({'code': RETCODE.DBERR, 'errrmsg': '新增地址失败'})

        address_dict = {
            "id": address.id,
            "title": address.title,
            "receiver": address.receiver,
            "province": address.province.name,
            "city": address.city.name,
            "district": address.district.name,
            "place": address.place,
            "mobile": address.mobile,
            "tel": address.tel,
            "email": address.email
        }

        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '新增地址成功', 'address': address_dict})


# 修改和删除地址
class AddressUpdateView(View):
    # 修改地址
    def put(self, request, address_id):
        # 接收参数
        json_dict = json.loads(request.body.decode())
        receiver = json_dict.get('receiver')
        province_id = json_dict.get('province_id')
        city_id = json_dict.get('city_id')
        district_id = json_dict.get('district_id')
        place = json_dict.get('place')
        mobile = json_dict.get('mobile')
        tel = json_dict.get('tel')
        email = json_dict.get('email')
        # 校验参数
        if not all([receiver, province_id, city_id, district_id, place, mobile, tel, email]):
            return http.HttpResponseBadRequest('缺少必传参数')
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseBadRequest('参数mobile有误')
        if tel:
            if not re.match(r'^(0[0-9]{2,3}-)?([2-9][0-9]{6,7})+(-[0-9]{1,4})?$', tel):
                return http.HttpResponseBadRequest('参数tel有误')
        if email:
            if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
                return http.HttpResponseBadRequest('参数email有误')

        # 更新地址信息
        try:
            Address.objects.filter(id=address_id).update(
                user=request.user,
                title=receiver,
                receiver=receiver,
                province_id=province_id,
                city_id=city_id,
                district_id=district_id,
                place=place,
                mobile=mobile,
                tel=tel,
                email=email
            )
        except Exception as e:
            logger.error(e)
            return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '更新地址失败'})

        # 构造响应数据
        address = Address.objects.get(id=address_id)
        updata_data = {
            "id": address.id,
            "title": address.title,
            "receiver": address.receiver,
            "province": address.province.name,
            "city": address.city.name,
            "district": address.district.name,
            "place": address.place,
            "mobile": address.mobile,
            "tel": address.tel,
            "email": address.email
        }
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '更新地址成功', 'address': updata_data})

    def delete(self, reuqest, address_id):

        try:
            # 查询要删除的地址
            address = Address.objects.get(id=address_id)
            # 将地址逻辑删除设置为True
            address.is_deleted = True
            address.save()
        except Exception as e:
            logger.error(e)
            return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '删除地址失败'})

        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '删除地址成功'})


# 设置默认地址
class DefaultAddressView(View):
    def put(self, request, address_id):
        try:
            # 接收地址参数
            address = Address.objects.get(id=address_id)
            # 设置地址为默认地址
            request.user.default_address = address
            request.user.save()
        except Exception as e:
            logger.error(e)
            return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '设置默认地址失败'})
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '设置默认地址成功'})


# 修改地址标题
class UpdateAddressTitleView(View):
    def put(self, request, address_id):
        # 接收地址标题参数
        json_dict = json.loads(request.body.decode())
        title = json_dict.get('title')
        try:
            address = Address.objects.get(id=address_id)
            address.title = title
            address.save()
        except Exception as e:
            logger.error(e)
            return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '设置地址标题失败'})
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '设置地址标题成功'})


# 修改密码
class ChangePasswordView(View):
    def get(self, request):
        return render(request, 'user_center_pass.html')

    def post(self, request):
        # 接收密码参数
        old_password = request.POST.get('old_password')
        new_password = request.POST.get('new_password')
        new_password2 = request.POST.get('new_password2')
        # 校验参数
        if not all([old_password, new_password, new_password2]):
            return http.HttpResponseBadRequest('缺少必传参数')
        if not re.match(r'^[0-9A-Za-z]{8,20}$', new_password2):
            return http.HttpResponseBadRequest('密码格式错误')
        if new_password != new_password2:
            return http.HttpResponseBadRequest('两次输入的密码不一致')
        # 验证原始密码是否正确
        if not request.user.check_password(old_password):
            return render(request, 'user_center_pass.html', {'origin_password_errmsg': '原始密码错误'})
        # 更新密码
        try:
            request.user.set_password(new_password)
            request.user.save()
        except Exception as e:
            logger.error(e)
            return render(request, 'user_center_pass.html', {'change_password_errmsg': '修改密码失败'})

        # 退出登陆,删除登录信息
        logger(request)
        # 重定向首页登陆
        response = redirect(reverse('user:login'))
        response.delete_cookie('username')
        return response


# 用户浏览记录
class HistoryView(LoginRequiredMixin, View):
    '''
        1.接收数据
        2.验证数据
        3.数据保存在redis中
            3.1 连接redis
            3.2 先去重
            3.3 再添加
            3.4 列表中只保存5条记录
        4.返回相应
    '''

    def post(self, request):
        data = json.loads(request.body.decode())
        sku_id = data.get('sku_id')
        try:
            SKU.objects.get(id=sku_id)
        except SKU.DoesNotExist:
            return http.JsonResponse({'code': RETCODE.NODATAERR, 'errmsg': '商品不存在'})

        # 保存用户浏览数据
        redis_conn = get_redis_connection('history')

        # 去重  redis_conn.lrem(key,count,value)
        redis_conn.lrem('history:%s' % request.user_id, 0, sku_id)
        # 添加  redis_conn.lpush(key,value)
        redis_conn.lpush('history:%s' % request.user_id, sku_id)
        # 截取  redis_conn.ltrim(key,start,stop)
        redis_conn.ltrim('history:%s' % request.user_id, 0, 4)
        # 返回响应
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'ok'})

    def get(self, request):
        redis_conn = get_redis_connection('history')
        sku_ids = redis_conn.lrange('history:%s' % request.user.id, 0, 4)
        skus = []
        for id in sku_ids:
            sku = SKU.objects.get(id=id)
            skus.append({
                'id': sku.id,
                'name': sku.name,
                'default_image_url': sku.default_image.url,
                'price': sku.price,
            })

        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'ok', 'skus': skus})
